import { RadiusSettingOutlined, SmallDashOutlined } from "@ant-design/icons";
import { notification } from "antd";
import $ from "jquery";
import { Feature, Overlay } from "ol";
import Geometry from "ol/geom/Geometry";
import LineString from "ol/geom/LineString";
import Polygon from "ol/geom/Polygon";
import { Draw } from "ol/interaction";
import VectorLayer from "ol/layer/Vector";
import { unByKey } from "ol/Observable";
import VectorSource from "ol/source/Vector";
import { getArea, getLength } from "ol/sphere";
import { Circle as CircleStyle } from "ol/style";
import Fill from "ol/style/Fill";
import Stroke from "ol/style/Stroke";
import Style from "ol/style/Style";
import { getMainMap } from "./MainMap";
import "./measurelib.css";

type MeasureType = "Polygon" | "LineString";

let measureFlag = false;

export function isMeasuring(): boolean {
  return measureFlag;
}

export function beginMeasure(measureType: MeasureType) {
  if (vector === null) {
    vector = new VectorLayer({
      source: source,
      style: new Style({
        fill: new Fill({
          color: "rgba(255, 255, 255, 0.2)",
        }),
        stroke: new Stroke({
          color: "#3B2667",
          width: 2,
        }),
        image: new CircleStyle({
          radius: 7,
          fill: new Fill({
            color: "#3B2667",
          }),
        }),
      }),
    });
    getMainMap().addLayer(vector);
  }
  doneMeasure();
  displayHelpMessage(measureType);
  addInteraction(measureType);
  measureFlag = true;
}

export function doneMeasure() {
  if (draw !== null) {
    getMainMap().removeInteraction(draw);
    getMainMap().removeOverlay(measureTooltip as Overlay);
    $(".ol-tooltip").remove();
    draw = null;
    source.clear();
  }
  measureFlag = false;
}

function displayHelpMessage(measureType: MeasureType) {
  switch (measureType) {
    case "LineString":
      notification.open({
        message: "距离测量",
        icon: <SmallDashOutlined />,
        description:
          "在合适的位置单击鼠标左键建立一个折点，双击鼠标左键结束测量。",
      });
      break;
    case "Polygon":
      notification.open({
        message: "面积测量",
        icon: <RadiusSettingOutlined />,
        description:
          "在合适的位置单击鼠标左键建立一个折点，双击鼠标左键结束测量。",
      });
      break;
  }
}

const source = new VectorSource();

let vector: VectorLayer<VectorSource<Geometry>> | null = null;

let draw: Draw | null = null;

let sketch: Feature<any> | null = null;

let measureTooltipElement: HTMLElement | null = null;

let measureTooltip: Overlay | null = null;

function addInteraction(measureType: MeasureType) {
  draw = new Draw({
    source: source,
    type: measureType,
    style: new Style({
      fill: new Fill({
        color: "rgba(255, 255, 255, 0.2)",
      }),
      stroke: new Stroke({
        color: "rgba(0, 0, 0, 0.5)",
        lineDash: [10, 10],
        width: 2,
      }),
      image: new CircleStyle({
        radius: 5,
        stroke: new Stroke({
          color: "rgba(0, 0, 0, 0.7)",
        }),
        fill: new Fill({
          color: "rgba(255, 255, 255, 0.2)",
        }),
      }),
    }),
  });
  getMainMap().addInteraction(draw);

  createMeasureTooltip();

  let listener: any;
  draw.on("drawstart", (evt) => {
    sketch = evt.feature as Feature<any>;

    // @ts-ignore
    let tooltipCoord = evt.coordinate;
    listener = sketch.getGeometry().on("change", (evt: { target: any }) => {
      const geom = evt.target;
      let output: string = "";
      if (geom instanceof Polygon) {
        output = formatArea(geom);
        tooltipCoord = geom.getInteriorPoint().getCoordinates();
      } else if (geom instanceof LineString) {
        output = formatLength(geom);
        tooltipCoord = geom.getLastCoordinate();
      }
      if (measureTooltip !== null && measureTooltipElement !== null) {
        measureTooltipElement.innerHTML = output;
        measureTooltip.setPosition(tooltipCoord);
      }
    });
  });

  draw.on("drawend", function () {
    if (measureTooltip !== null && measureTooltipElement !== null) {
      measureTooltipElement.className = "ol-tooltip ol-tooltip-static";
      measureTooltip.setOffset([0, -7]);
    }
    sketch = null;
    // @ts-ignore
    measureTooltipElement = null;
    createMeasureTooltip();
    unByKey(listener);
  });
}

function createMeasureTooltip() {
  if (measureTooltipElement !== null) {
    // @ts-ignore
    measureTooltipElement.parentNode.removeChild(measureTooltipElement);
  }
  measureTooltipElement = document.createElement("div");
  measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
  measureTooltip = new Overlay({
    element: measureTooltipElement,
    offset: [0, -15],
    positioning: "bottom-center",
    stopEvent: false,
    insertFirst: false,
  });
  getMainMap().addOverlay(measureTooltip);
}

function formatLength(line: Geometry) {
  const length = getLength(line) * 1000000;
  return length > 100
    ? `${Math.round((length / 1000) * 100) / 100} km`
    : `${Math.round(length * 100) / 100} m`;
}

function formatArea(polygon: Geometry) {
  const area = getArea(polygon) * 1000000000000;
  return area > 10000
    ? `${Math.round((area / 1000000) * 100) / 100} km<sup>2</sup>`
    : `${Math.round(area * 100) / 100} m<sup>2</sup>`;
}
